package com.ezlcp.form.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ezlcp.commons.base.db.BaseDao;
import com.ezlcp.commons.base.db.BaseService;
import com.ezlcp.commons.base.entity.JsonPageResult;
import com.ezlcp.commons.base.entity.JsonResult;
import com.ezlcp.commons.base.search.QueryFilter;
import com.ezlcp.commons.base.search.QueryParam;
import com.ezlcp.commons.constant.Constants;
import com.ezlcp.commons.constant.ListTypeEnum;
import com.ezlcp.commons.service.impl.SuperServiceImpl;
import com.ezlcp.commons.tool.IdGenerator;
import com.ezlcp.commons.tool.StringUtils;
import com.ezlcp.commons.utils.ContextUtil;
import com.ezlcp.form.db.DBHelper;
import com.ezlcp.form.entity.DataList;
import com.ezlcp.form.entity.ListCol;
import com.ezlcp.form.mapper.DataListMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * [查询列表定义]业务服务类
 */
@Service
public class DataListServiceImpl extends SuperServiceImpl<DataListMapper, DataList> implements BaseService<DataList> {
    @Resource
    private DataListMapper dataListMapper;
    @Resource
    private ListColServiceImpl listColService;
    @Resource
    private EntityServiceImpl entityService;
    @Resource
    private ModuleServiceImpl moduleService;

    /***
     * 获取列表类型为表格的实例的分页数据
     * @param listId 列表ID
     * @param queryFilter 查询条件对象
     */
    public JsonPageResult getDataOfTable(String listId, QueryFilter queryFilter) {
        var result = JsonPageResult.getSuccess("common.handleSuccess");
        var list = this.getBaseMapper().selectById(listId);
        if (list == null || list.getListType() != ListTypeEnum.Table.getId() || StringUtils.isEmpty(list.getEntId())) {
            return JsonPageResult.getFail("common.paramError");
        }
        String entId = list.getEntId();
        var entity = entityService.get(entId);
        var cols = getListCols(list.getId());
        if (entity == null || cols == null || cols.isEmpty()) {
            return JsonPageResult.getFail("common.paramError");
        }
        list.setCols(cols);
        var page = queryFilter.getPage();
        try {
            boolean hasTenantField = false;
            for (var col : entity.getCols()) {
                if (Constants.COL_TENANT_ID.equals(col.getFieldName().toLowerCase())) {
                    hasTenantField = true;
                    break;
                }
            }
            String whereSql = "";
            var params = queryFilter.getQueryParams();
            if (params != null && !params.isEmpty()) {
                for (var param : params.values()) {
                    String opType = param.getOpType();
                    String fieldType = param.getFieldType();
                    String fieldName = param.fieldName;
                    Object value = QueryParam.getObjValue(opType, fieldType, param.getValue().toString());
                    if (QueryParam.OP_IN.equals(opType)) {
                        whereSql += " AND " + fieldName + " IN (" + value + ")";
                    } else {
                        if (QueryParam.FIELD_TYPE_STRING.equals(fieldType) || QueryParam.FIELD_TYPE_DATE.equals(fieldType)) {
                            value = "'" + value + "'";
                        }
                        whereSql += " AND " + fieldName + " " + param.getOperateStr() + " " + value;
                    }
                }
            }
            String orderBySql = queryFilter.getSortSql();
            var client = DBHelper.getDbClient(entity.getDsId());
            String sql = getDataListSql(list);
            String tenantId = ContextUtil.getCurrentTenantId();
            int index = sql.lastIndexOf(" ORDER BY ");
            if (index < 0) {
                if (StringUtils.isNotEmpty(whereSql)) {
                    sql += whereSql;
                }
                if (hasTenantField && StringUtils.isNotEmpty(tenantId)) {
                    sql += " AND " + Constants.COL_TENANT_ID + "='" + tenantId + "' ";
                }
                if (StringUtils.isNotEmpty(orderBySql)) {
                    sql += " ORDER BY " + orderBySql;
                }
            } else {
                String fixedOrderBy = sql.substring(index);
                sql = sql.substring(0, index);
                if (StringUtils.isNotEmpty(whereSql)) {
                    sql += whereSql;
                }
                if (hasTenantField && StringUtils.isNotEmpty(tenantId)) {
                    sql += " AND " + Constants.COL_TENANT_ID + "='" + tenantId + "' ";
                }
                sql += fixedOrderBy;
                if (StringUtils.isNotEmpty(orderBySql)) {
                    sql += "," + orderBySql;
                }
            }
            index = sql.indexOf(" FROM ");
            String countSql = "SELECT COUNT(*) " + sql.substring(index);
            countSql = client.convert2Native(countSql);
            String beforeSql = list.getBeforeSql();
            var jdbcTemplate = client.getJdbcTemplate();
            if (StringUtils.isNotEmpty(beforeSql)) {
                jdbcTemplate.execute(beforeSql);
            }
            var count = jdbcTemplate.queryForObject(countSql, Integer.class);

            page.setTotal(count);
            //查询总记录数为0，则无法查详细数据
            if (count == 0) {
                page.setRecords(new ArrayList());
                result.setPageData(page);
                return result;
            }
            String pagedSql = client.getPagedSql(sql, (int) page.getCurrent(), (int) page.getSize());
            log.debug("生成的分页查询语句：=======================\n" + pagedSql);
            var data = jdbcTemplate.queryForList(pagedSql);
            page.setRecords(data);
            result.setPageData(page);
            return result;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            var fail = JsonPageResult.getFail(e.getMessage());
            fail.setPageData(page);
            return fail;
        }
    }

    /***
     * 发布数据列表
     * @param id 列表ID
     */
    public JsonResult publish(String id) {
        var list = this.getBaseMapper().selectById(id);
        if (list == null || list.getStatus() == 4) {
            return JsonResult.Fail("common.paramError");
        }
        list.setSeq(list.getSeq() + 1);
        //再次发布
        if (list.getStatus() == 1) {
            list.setVer(list.getVer() + 1);
        } else {
            list.setVer(1);
            list.setStatus(Constants.SHORT1);
        }
        this.getBaseMapper().updateById(list);
        return JsonResult.Success("common.handleSuccess");
    }

    @Override
    public DataList get(Serializable id) {
        var list = BaseService.super.get(id);
        if (list != null) {
            //同时查询出相关的字段
            var cols = getListCols(list.getId());
            list.setCols(cols);
            //查询模块名和实体名
            var entity = entityService.getBaseMapper().selectById(list.getEntId());
            if (entity != null) {
                list.setEntName(entity.getEntName());
                list.setEnEntName(entity.getEnName());
                list.setHkEntName(entity.getHkName());
                list.setMainTableName(entity.getTableName());
            }
            var module = moduleService.getBaseMapper().selectById(list.getModuleId());
            if (module != null) {
                list.setModuleName(module.getModuleName());
                list.setEnModuleName(module.getEnName());
                list.setHkModuleName(module.getHkName());
            }
        }
        return list;
    }

    /***
     * 查询数据列表的字段配置
     * @param listId 列表ID
     * @return java.util.List<com.ezlcp.form.entity.ListCol>
     */
    private List<ListCol> getListCols(String listId) {
        QueryWrapper<ListCol> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(ListCol::getListId, listId).orderByAsc(ListCol::getColOrder);
        return listColService.getBaseMapper().selectList(wrapper);
    }

    /***
     * 获取数据列表的最终会生成的SQL语句
     * @param list 数据列表信息
     * @return java.lang.String
     */
    public String getDataListSql(DataList list) {
        try {
            String entId = list.getEntId();
            var entity = entityService.getBaseMapper().selectById(entId);
            StringBuilder sb = new StringBuilder();
            sb.append("SELECT main.id as pkId");
            for (var col : list.getCols()) {
                sb.append(",");
                String tableName = col.getTableAlias();
                if (StringUtils.isNotEmpty(tableName)) {
                    sb.append(tableName).append(".");
                }
                sb.append(col.getFieldName());
                String alias = col.getFieldAlias();
                if (StringUtils.isNotEmpty(alias)) {
                    sb.append(" AS ").append(alias);
                }
            }

            sb.append(" FROM ").append(entity.getTableName()).append(" AS main ");
            String strJoin = list.getSqlJoin();
            if (StringUtils.isNotEmpty(strJoin)) {
                sb.append(strJoin).append(" ");
            }
            String strWhere = list.getSqlWhere();
            sb.append(" WHERE 1=1 ");
            if (StringUtils.isNotEmpty(strWhere)) {
                strWhere = strWhere.trim();
                if (StringUtils.isNotEmpty(strWhere)) {
                    if (!strWhere.toLowerCase().startsWith("and ")) {
                        sb.append(" AND ");
                    }
                    sb.append(strWhere);
                }
            }
            sb.append(" ");
            String strOrderBy = list.getSqlOderBy();
            if (StringUtils.isNotEmpty(strOrderBy)) {
                strOrderBy = strOrderBy.trim();
                if (StringUtils.isNotEmpty(strOrderBy)) {
                    if (!strWhere.toLowerCase().startsWith("order ")) {
                        sb.append("ORDER BY ");
                    }
                    sb.append(strOrderBy);
                }
            }
            return sb.toString();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return "";
    }

    /***
     * 处理SQL字段的中大于和小于号的转义字符
     * @param list
     */
    private void dealEscapeChar(DataList list) {
        if (StringUtils.isNotEmpty(list.getSqlJoin())) {
            list.setSqlJoin(list.getSqlJoin().trim().replace("&gt;", ">").replace("&lt;", "<"));
        }
        if (StringUtils.isNotEmpty(list.getSqlWhere())) {
            list.setSqlWhere(list.getSqlWhere().trim().replace("&gt;", ">").replace("&lt;", "<"));
        }
        if (StringUtils.isNotEmpty(list.getSqlOderBy())) {
            list.setSqlOderBy(list.getSqlOderBy().trim().replace("&gt;", ">").replace("&lt;", "<"));
        }
        if (StringUtils.isNotEmpty(list.getBeforeSql())) {
            list.setBeforeSql(list.getBeforeSql().trim().replace("&gt;", ">").replace("&lt;", "<"));
        }
        if (StringUtils.isNotEmpty(list.getSqlBeforeDel())) {
            list.setSqlBeforeDel(list.getSqlBeforeDel().trim().replace("&gt;", ">").replace("&lt;", "<"));
        }
        if (StringUtils.isNotEmpty(list.getSqlAfterDel())) {
            list.setSqlAfterDel(list.getSqlAfterDel().trim().replace("&gt;", ">").replace("&lt;", "<"));
        }
    }

    /***
     * @description 保存数据列表信息
     * @param list 数据列表信息
     * @param delColIds 要删除的列ID
     */
    @Transactional
    public JsonResult saveDataList(DataList list, String delColIds) {
        String listId = list.getPkId();
        String tenantId = ContextUtil.getCurrentTenantId();
        dealEscapeChar(list);
        //先保存主表
        if (StringUtils.isEmpty(listId)) {
            listId = IdGenerator.getIdStr();
            list.setPkId(listId);
            list.setTenantId(tenantId);
            list.setSeq(1);
            list.setStatus(Constants.SHORT0);
            this.insert(list);
        } else {
            list.setSeq(list.getSeq() + 1);
            this.update(list);
        }
        var result = JsonResult.Success("common.handleSuccess");
        //保存列表列
        var cols = list.getCols();
        //修改的列
        var olds = cols.stream().filter(col -> StringUtils.isNotEmpty(col.getPkId()))
                .collect(Collectors.toList());
        if (olds != null && !olds.isEmpty()) {
            for (var col : olds) {
                col.setSeq(col.getSeq() + 1);
            }
            listColService.updateBatchById(olds);
        }
        //新增的列
        var news = cols.stream().filter(col -> StringUtils.isEmpty(col.getPkId()))
                .collect(Collectors.toList());
        if (news != null && !news.isEmpty()) {
            for (var col : news) {
                col.setPkId(IdGenerator.getIdStr());
                col.setListId(listId);
                col.setTenantId(tenantId);
                col.setSeq(1);
            }
            listColService.saveBatch(news);
        }
        //是否有要删除的列ID
        if (StringUtils.isEmpty(delColIds)) {
            return result;
        }
        var arrIds = delColIds.split(",");
        if (arrIds.length > 0) {
            listColService.removeBatchByIds(Arrays.asList(arrIds));
        }
        return result;
    }


    @Override
    public BaseDao<DataList> getRepository() {
        return dataListMapper;
    }
}